package cn.com.idmy.auth.session;

import cn.com.idmy.auth.login.LoginState;
import cn.com.idmy.auth.token.TokenManager;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

@Data
@Accessors(fluent = true)
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true)
public abstract class SessionTokenManager<ID> extends TokenManager<ID> {
    protected final SessionManager<ID> sessionManager;

    @NotNull
    public Session<ID> session() {
        return sessionManager.getOrCreate(id());
    }

    @Override
    public void set(@NotNull LoginState<ID> state) {
        super.set(state);
        var session = session();
        session.addToken(state.token(), state.config().device(), state.data());
        session.update();
    }

    @Nullable
    @Override
    public String get(@NotNull LoginState<ID> state) {
        if (sessionManager.sessionConfig().isSessionEnabled()) {
            var concurrent = sessionManager.sessionStrategy().concurrent().apply(state.id());
            if (concurrent == ConcurrentStrategy.DEVICE || concurrent == ConcurrentStrategy.DISABLED) {
                sessionManager.replace(state.id(), state.config().device());
            }

            if (state.token() != null) {
                return state.token();
            }

            if (concurrent == ConcurrentStrategy.DEVICE || concurrent == ConcurrentStrategy.DISABLED) {
                var session = sessionManager.get(state.id());
                if (session != null) {
                    return session.getToken(state.config().device());
                }
            }
        }
        return state.token();
    }
}
